package featuresWindows;

import helpFeaturesWindows.HelpHoleWindow;
import j3d.J3D;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import CAD.MainFrame;

import operationSolids.CompoundSolid;

import features.Block;
import features.Feature;
import features.FlatHoleBottom;
import featuresWindows.CreateSlot.SlotDinamicBottomPanel;

import visualCAD.holeWindowView;


public class CreateHole extends holeWindowView implements ActionListener
{


	private J3D j3d = null;
	private HoleDinamicTopPanel holeTopPanel;
	private HoleDinamicBottomPanel holeBottomPanel;
	double  positionX = 0,
			positionY = 0,	
			positionZ = 0,
			radius = 0,
			depth = 0;
	
	public CreateHole(J3D j3d, Block block)
	{
		this.j3d = j3d;
		holeSplitPanel.setDividerLocation(0.5);
		holeSplitPanel.setTopComponent(holeTopPanel=new HoleDinamicTopPanel(positionX,positionY,radius));
		holeSplitPanel.setBottomComponent(holeBottomPanel=new HoleDinamicBottomPanel(positionX,positionZ,2*radius,depth));
		this.init();
	}
	public void init()
	{
		double y = holeTopPanel.faceY;
		double x = holeTopPanel.faceX;
		double z = holeTopPanel.faceZ;
		
		SpinnerModel zModel = new SpinnerNumberModel(0.0,-z, 0.0, 0.1);
		SpinnerModel yModel = new SpinnerNumberModel(0.0,0.0, y, 0.1);
		SpinnerModel xModel = new SpinnerNumberModel(0.0,0.0, x, 0.1);
		SpinnerModel depthModel = new SpinnerNumberModel(0.0,0.0, z, 0.1);
		SpinnerModel diameterModel = new SpinnerNumberModel(0.0,0.0, null, 0.1);
		zPositionSpinner.setModel(zModel);
		xPositionSpinner.setModel(xModel);
		yPositionSpinner.setModel(yModel);
		depthSpinner.setModel(depthModel);
		diameterSpinner.setModel(diameterModel);
		
		this.diameterSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		yPositionSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		zPositionSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		xPositionSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		depthSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		
		helpButton.addActionListener(this);
		this.submitButton.addActionListener(this);
		this.cancelButton.addActionListener(this);
		this.setResizable(false);
	}
	
	private void redrawDynamicComponents(){
		try{
			radius=(Double)diameterSpinner.getValue()/2;
			positionX=(Double)xPositionSpinner.getValue();
			positionY=(Double)yPositionSpinner.getValue();
			positionZ=(Double)zPositionSpinner.getValue();
			depth=(Double)depthSpinner.getValue();
			}
			catch (Exception e1) {
				JOptionPane.showMessageDialog(null, "error in entering data");
			}
			holeSplitPanel.setTopComponent(holeTopPanel=new HoleDinamicTopPanel(positionX,positionY,radius));
			holeSplitPanel.setBottomComponent(holeBottomPanel=new HoleDinamicBottomPanel(positionX,positionZ,2*radius,depth));
			holeSplitPanel.setDividerLocation(0.5);
	}
	public void cancel()
	{
		dispose();
	}
	public void ok()
	{
		boolean ok = true;
	
		
		//----------- positionX validation -----------//
		
		if (ok)
		{
			try
			{
				positionX = (Double)this.xPositionSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		
		//------------- positionY validation ------------//
		
		if (ok)
		{
			try
			{
				positionY = (Double)this.zPositionSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//------------- positionZ validation -------------//
		
		if (ok)
		{
			try
			{
				positionZ = -(Double)this.yPositionSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//-------------- radius Validation ---------------//
		if (ok)
		{
			try
			{
				radius = (Double)this.diameterSpinner.getValue()/2;
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		//-------------- depth Validation ---------------//
		if (ok)
		{
			try
			{
				depth = (Double)this.depthSpinner.getValue();
			}
			catch (Exception e)
			{
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		} 
		if(ok){
			
		FlatHoleBottom hole = new FlatHoleBottom(Feature.FLATHOLEBOTTOM, null, (float)depth, (float)(radius), (float)(positionX),(float)(positionY),(float)(positionZ), this.nameTextField.getText(),MainFrame.Face);
		this.j3d.removeSolid();
		this.j3d.addSolid(MainFrame.block.block);
		this.dispose();
		
		}
	}

	@Override
	public void actionPerformed(ActionEvent event) 
	{
		// TODO Auto-generated method stub
		Object origin = event.getSource();
		
		
		if (origin.equals(cancelButton))
		{
			this.cancel();
		} else if (origin.equals(submitButton))
		{
			this.ok();
		}else if (origin.equals(helpButton)){
			new HelpHoleWindow();
		}
	}
}
class HoleDinamicTopPanel extends JComponent{

	Shape hole;
	Shape box;
	Shape axisX, axisY;
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier= 0;
	double positionX,positionY, radius = 0;
	
	
	private void findXandY() {
		switch(MainFrame.Face){
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}
	private double calculateMultiplier() {
		double multiplier = 195/faceY;
		if(faceX*multiplier > 370){
			multiplier = 370/faceX;
		}
		if(faceZ*multiplier > 180){
			multiplier = 180/faceZ;
		}
		return multiplier;
	}
	public HoleDinamicTopPanel(double positionX, double positionY, double radius) {
		super();
		findXandY();
		multiplier = calculateMultiplier();
		this.positionX = positionX;
		this.positionY = positionY;
		this.radius = radius;
		hole=createHole(multiplier*(positionX),multiplier*(positionY),multiplier*(radius));
		box=createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
	}
	protected Shape createHole(double posX,double posY, double radius) {
		Shape circle = new Ellipse2D.Double((posX + 10 - radius), (posY + 20 - radius), radius*2, radius*2);
		return circle;
	}
	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceY*multiplier);
		return rectangle;
	}
	protected Shape verticalLine() {
		
		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}
	protected Shape horizontalLine(){
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}
	
	
	public void paint(Graphics g) {
		double translateX, translateY = 0;
		translateY = this.multiplier * faceY;
		//System.out.println("translateY = " + translateY);
		Graphics2D g2 = (Graphics2D) g;
		g2.scale(1, -1);
		g2.translate(0, -215);
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		
		g2.setPaint(new Color(211, 211, 211));
		g2.fill(box);
		g2.setPaint(Color.BLACK);
		g2.draw(box);
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(hole);
		g2.setPaint(Color.BLUE);
		g2.draw(hole);
		g2.setPaint(Color.RED);
		g2.draw(axisX);
		g2.draw(axisY);
		g2.scale(1, -1);
		g2.drawString("X", 50 ,-10);
		g2.drawString("Y", 0, -50);
		int x = (int) (multiplier*(positionX));
		int y = (int) (multiplier*(positionY));
		g2.drawString("x", x+8 ,-y-16);
		
	}
}
class HoleDinamicBottomPanel extends JComponent{
	
	Shape smallBox;
	Shape bigBox;
	Shape axisX, axisY, centerLine;
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier= 0;
	
	
	private void findXandY() {
		switch(MainFrame.Face){
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}
	private double calculateMultiplier() {
		double multiplier = 195/faceY;
		if(faceX*multiplier > 310){
			multiplier = 310/faceX;
		}
		if(faceZ*multiplier > 180){
			multiplier = 180/faceZ;
		}
		return multiplier;
	}
	
	public HoleDinamicBottomPanel(double positionX, double positionZ, double d1, double depth) {
		super();
		findXandY();
		multiplier = calculateMultiplier();
		smallBox=createBox(multiplier*(positionX-(d1/2)),multiplier*(-positionZ),multiplier*(d1),multiplier*(depth));
		bigBox=createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
		centerLine = centerLine(multiplier*(positionX-(d1/2)), multiplier*(-positionZ), multiplier*(d1), multiplier*(depth));
	}
	protected Shape createBox(double posX,double posY, double d1, double d2) {
		Shape rectangle = new Rectangle2D.Double(10+posX, 20+posY, d1, d2);
		return rectangle;
	}
	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10,20,faceX*multiplier,faceZ*multiplier);
		return rectangle;
	}
	protected Shape verticalLine() {
		
		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}
	protected Shape horizontalLine(){
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}
	protected Shape centerLine(double posX, double posY, double d1, double depth){
		Shape axisX = new Line2D.Double(10+posX+(d1/2), 20+posY, 10+posX+(d1/2), 20+posY+depth);
		return axisX;
	}
	
	
	public void paint(Graphics g) {
		//System.out.println("translateY = " + translateY);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		float dash1[] = {2.5f, 2.5f};
		float dash2[] = {3f, 1.5f,1f,1.5f};
		
		g2.setPaint(new Color(211, 211, 211));
		g2.fill(bigBox);
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(smallBox);
		g2.setPaint(Color.BLUE);
		g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 
				BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f));
		g2.draw(smallBox);
		g2.setPaint(Color.BLACK);
		g2.setStroke(new BasicStroke());
		g2.draw(bigBox);
		g2.setPaint(Color.RED);
		g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, 
				BasicStroke.JOIN_MITER, 10.0f, dash2, 0.0f));
		g2.draw(centerLine);
		g2.draw(axisX);
		g2.draw(axisY);
		g2.drawString("X", 50 ,20);
		g2.drawString("-Z", 0, 50);
	}
}

